package fnsvr

import "github.com/panjf2000/ants"

type asyncTask[T any] struct {
	co       func() (T, error)
	callback func(result T, err error)
}

type asyncTaskResult[T any] struct {
	callback func(result T, err error)
	result   T
	err      error
}

// 异步调用管理器
type AsyncCallMgr[T any] struct {
	pool     *ants.PoolWithFunc
	taskChan chan *asyncTaskResult[T]
}

// Invoke 执行一个异步调用
func (m *AsyncCallMgr[T]) Invoke(
	co func() (T, error),
	callback func(result T, err error),
) error {
	return m.pool.Invoke(&asyncTask[T]{
		co:       co,
		callback: callback,
	})
}

// Loop 从任务通道中取出任务并执行
func (m *AsyncCallMgr[T]) Loop() {
	for {
		v, ok := ReadNonBlocking(m.taskChan)
		if !ok {
			return
		}

		v.callback(v.result, v.err)
	}
}

// 创建一个新的异步调用管理器
func NewAsyncCallMgr[T any](size int) (*AsyncCallMgr[T], error) {
	taskChan := make(chan *asyncTaskResult[T], size)

	taskFn := func(data any) {
		task := data.(*asyncTask[T])
		re, err := task.co()
		taskResult := &asyncTaskResult[T]{
			callback: task.callback,
			result:   re,
			err:      err,
		}

		taskChan <- taskResult
	}

	pool, err := ants.NewPoolWithFunc(size, taskFn)
	if err != nil {
		close(taskChan)
		return nil, err
	}

	return &AsyncCallMgr[T]{
		pool:     pool,
		taskChan: taskChan,
	}, nil
}
